<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>问题一响应式原理</title>
</head>
<body>
  <div id="app"></div>
</body>
<script>
  // 使用defineProperty的缺点是 会把所有属性都重新定义一遍 有性能问题  Vue3使用proxy来解决这个问题
  let data = { // 1. 变成响应式的数据
    count: 0
  }

  let active // 2. 临时存放watcher
  function defineReactive(obj) {
    for (let key in obj) { // 重新定义数据的各个属性
      let value = obj[key]
      let dep = [] // 依赖数组 用于依赖收集
      Object.defineProperty(obj, key, {
        get () { // 属性的get方法
          if (active) {
            dep.push(active) // 依赖收集
          }
          return value // 返回该属性值
        },
        set (newValue) { // 属性的set方法
          value = newValue // 修改当前值
          dep.forEach(watch => watch()) // 通知依赖更新视图
        }
      })
    }
  }

  defineReactive(data) // 将对象的属性 响应式化

  // 插入到页面的功能 需要保存
  const watcher = fn => {
    active = fn
    fn() // 调用函数
    active = null
  }

  watcher(() => {
    app.innerHTML = data.count // 这里会执行get方法 这里模拟一个组件读取属性
  })
  // 在控制台中，输入data.count = 77777 会执行set方法 看到页面绑定的值发生了变化
</script>
</html>